package com.mxchip.livestar.ui.call


import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.trello.lifecycle2.android.lifecycle.AndroidLifecycle
import com.trello.rxlifecycle3.LifecycleProvider
import com.mxchip.livestar.R
import com.mxchip.livestar.base.CallLogViewModel
import com.mxchip.livestar.utils.FileLog
import com.mxchip.livestar.rx.RxSchedulersHelper
import com.mxchip.livestar.base.SystemData
import com.mxchip.livestar.base.toast
import com.mxchip.livestar.repository.RoomClientRepository
import com.mxchip.livestar.rx.RxBus
import com.mxchip.livestar.rx.RxConstant
import com.mxchip.livestar.sound.LocalRingManagement
import com.videohigh.graham.SampleSDK
import com.videohigh.graham.SessionContext
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.fragment_red.*
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit

class RedFragment : Fragment() {

    private val provider: LifecycleProvider<Lifecycle.Event> = AndroidLifecycle.createLifecycleProvider(this)

    private val roomClientRepository = RoomClientRepository

    private val dbyViewModel by activityViewModels<DbyViewModel>()
    private val screenViewModel by activityViewModels<ScreenViewModel>()
    private val roomViewModel by activityViewModels<RoomViewModel>()
    private val callLogViewModel by viewModels<CallLogViewModel>()

    private val args: RedFragmentArgs by navArgs()

    private lateinit var sessionContext: SessionContext

    private lateinit var leaveCallEventObservable: Observable<SessionContext>

    private val compositeDisposable = CompositeDisposable()

    private val logger = FileLog.getLogger(RedFragment::class.java)

    // private val sampleSDK = SampleSDK.getInstance()

    override fun onDestroyView() {
        super.onDestroyView()
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_red, container, false)
    }

    @SuppressLint("CheckResult")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        sessionContext = args.sessionContext


        // 拨号方主动挂断
        leaveCallEventObservable = RxBus.get().register(RxConstant.LEAVE_CALL_EVENT, SessionContext::class.java)
        leaveCallEventObservable./*compose(provider.bindToLifecycle()).*/compose(RxSchedulersHelper.io_main())
                .subscribe(::onLeaveCall) { error ->
                    run {
                        logger.error(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                                " leaveCallEventObservable" + error.message)
                        error.printStackTrace()
                    }
                }

        Log.e("RedFragment", "invitationEvent $sessionContext")

        val terms = sessionContext.callList.plus(sessionContext.inviteList)

        Log.e("RedFragment", "sessionContext.callList: ${sessionContext.callList.toTypedArray().contentToString()}")

        // TODO: 回调数据加入邀请者ID
        val inviterTermId: String = sessionContext.from.termId

        val sessionsJoin = sessionContext.inviteList

        if (!sessionsJoin.isNullOrEmpty() && sessionsJoin.size > 1) {
            head_portrait.setImageResource(R.drawable.if_icon_group_filled)
            user_name.text = String.format(getString(R.string.invite_you_meetings), inviterTermId.trimStart('0'))
            val join = terms.map { it.termId }.joinToString(",") { it.trimStart('0') }
            phone_state.text = getString(R.string.other_participants) + join
        } else {
            head_portrait.setImageResource(R.drawable.if_icon_user)
            user_name.text = String.format("%s", inviterTermId.trimStart('0'))
            phone_state.text = getString(R.string.invite_you_meeting)
        }

        dbyViewModel.videoResInitFinish.observe(viewLifecycleOwner, Observer {
            lifecycleScope.launch {
                if (SystemData.autoAnswer && it) {
                    val nextInt = Random().nextInt(2000)
                    delay(nextInt.toLong() + 1000)
                    reqAccept()
                }
            }
        })

        startPlayLocalRing()

        button_accept.setOnClickListener {
            callLogViewModel.createCallLog(sessionContext.from.termId, "1")
            reqAccept()
        }

        button_reject.setOnClickListener {
            Log.e("RedFragment", "onRejectClick")
            callLogViewModel.createCallLog(sessionContext.from.termId, "3")
            stopPlayLocalRing()
            reqReject()
        }

        lifecycleScope.launch {
            delay(30 * 1000)
            timeout(0)
        }

        /*roomViewModel.sessionsAll.observe(viewLifecycleOwner, Observer {

            Log.e("RedFragment", "sessionsAll aa $it")

            if (it.contains(sessionContext.from.dbyUid)) {
                return@Observer
            }

            lifecycleScope.launch {
                toast("对方已挂断")
                delay(1000)
                reqHangup()
            }
        })*/
    }

    /**
     * 销毁
     */
    override fun onDestroy() {
        super.onDestroy()
        stopPlayLocalRing()
        RxBus.get().unregister(RxConstant.LEAVE_CALL_EVENT, leaveCallEventObservable)

        compositeDisposable.clear()
    }

    /**
     * 开始响铃
     */
    private fun startPlayLocalRing() {
        compositeDisposable.add(Observable.interval(0, 0, TimeUnit.MILLISECONDS)
                .compose(RxSchedulersHelper.io())
                .take(1)
                .subscribe { aLong: Long? -> LocalRingManagement.getInstance().playMusic(R.raw.called, context) })
    }

    /**
     * 停止响铃
     */
    private fun stopPlayLocalRing() {
        if (LocalRingManagement.getInstance().isPlaying) {
            LocalRingManagement.getInstance().stop()
        }
    }

    /**
     * 超时挂断
     */
    private fun timeout(time: Long) {

        Log.e("RedFragment", "timeout $time")

        callLogViewModel.createCallLog(sessionContext.from.termId, "3")
        reqTimeout()
    }

    /**
     * 发送应答请求
     */
    private fun reqAccept() {

        stopPlayLocalRing()
        logger.info(SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.CHINA).format(Date()) + "RedFragment::reqAccept: RoomClientRepository.acceptCall")

        roomClientRepository.enterCall({sessionContext ->

            lifecycleScope.launch {
                Log.e("RedFragment", "callback enterCall $sessionContext")

                val action = RedFragmentDirections.actionRedFragmentToCallControlFragment()

                findNavController().navigate(action)
            }

        }, {code, message ->
            lifecycleScope.launch {
                toast("错误代码: $code $message")
            }
        })
    }

    /**
     * 发送拒接请求
     */
    private fun reqReject() {
        reqHangup()
    }

    /**
     * 超时挂断
     */
    private fun reqTimeout() {
        Log.e("RedFragment", "reqTimeout")
        reqHangup()
    }

    /**
     * 发送挂断请求
     */
    private fun reqHangup() {
        stopPlayLocalRing()

        RoomClientRepository.endCall {
            Log.i("SampleSDK", "RedFragment on endCall")
            dbyViewModel.join(null)
        }
    }

    /**
     * 收到其他端的挂断请求
     */
    private fun onLeaveCall(session: SessionContext) {

        Log.e("RedFragment", "onLeaveCall: $session")

        val inviteList = session.inviteList
        val callList = session.callList

        if (inviteList.contains(session.from) || callList.contains(session.from)) {
            return
        }

        lifecycleScope.launch {
            toast("对方已挂断")
            delay(1000)
            reqHangup()
        }

    }

}
